import Animal from "./Animal.js";
import status from './runtime.js';
import { random, zipAnimalList } from "./tools.js";

export default class CanvasMap{
    private animalList:Map<number,Animal>=new Map();
    private powermap:number[][]=new Array(500).fill([]);
    animalPoints:(Animal|null)[][]=new Array(500).fill([]);
    private nextid=1
    constructor(){
        this.animalPoints=this.animalPoints.map(e=>{
            return (new Array(500)).fill(null)
        });
        this.powermap=this.powermap.map(e=>{
            return (new Array(500)).fill(255)
        });
    }

    get animalCount(){
        return this.animalList.size;
    }
    get historyAnimalCount(){
        return this.nextid-1;
    }

    /**
     * 动物在地图上移动
     * @param fx 
     * @param fy 
     * @param tx 
     * @param ty 
     */
    animalMove(fx:number,fy:number,tx:number,ty:number){
        if(tx>=250-status.radius&&ty>=250-status.radius&& tx<250+status.radius && ty <250+status.radius){
                let fromAnimal=this.animalPoints[fx][fy]
                if(fromAnimal && fromAnimal.power>1){
                    this.reducePower(fromAnimal);
                    if(!this.animalPoints[tx][ty]){
                        this.animalPoints[tx][ty]=fromAnimal;
                        this.animalPoints[fx][fy]=null;
                        return true;
                    }
                }
        }
        return false;
    }

    /**
     * 检查这个地方是否有生命
     */
    checkHaslife(x:number,y:number){
        if(x>0&&y>0&&x<500&&y<500)
            return !! this.animalPoints[x][y];
        else
            return false;
    }
    /**
     * 创建一个新生命
     * @param life 
     */
    create(child:Animal,parent:Animal){
        if(!this.checkHaslife(child.x,child.y)&& child.x>250-status.radius &&child.x<250+status.radius &&child.y>250-status.radius && child.y<250+status.radius){
            this.animalPoints[child.x][child.y]=child;
            child.id=this.nextid;
            child.power=Math.floor(parent.power/2);
            parent.power=child.power;
            let rdap=(v:number)=>{
                v=v+random(2)-1;
                v=v>15?15:v;
                v=v<0?0:v;
                return v;
            }
            if(random(15)<parent.wantChange){
                child.wantEat=rdap(parent.wantEat);
                child.wantsun=rdap(parent.wantsun);
                child.wantbreed=rdap(parent.wantbreed);
                child.wantmove=rdap(parent.wantmove);
                child.wantChange=rdap(parent.wantChange);
            }else{
                child.wantEat=parent.wantEat;
                child.wantsun=parent.wantsun;
                child.wantbreed=parent.wantbreed;
                child.wantmove=parent.wantmove;
                child.wantChange=parent.wantChange;
            }
            
            this.animalList.set(this.nextid,child);
            this.nextid++;
            return true;
        }
        return false;
    }

    createPowerMap(){
        let seedMap:number[][]=new Array(26).fill([]);
        seedMap=seedMap.map(()=>{
            let rel=new Array(26).fill(0);
            return rel.map(()=>random(255));
        });
        this.powermap=this.powermap.map((e,yi)=>{
            return e.map((p,xi)=>{
                const width=40;
                let spx=(xi-(xi%width))/width
                let spy=(yi-(yi%width))/width
                let ltv=seedMap[spy][spx];
                let rtv=seedMap[spy][spx+1];
                let lbv=seedMap[spy+1][spx];
                let rbv=seedMap[spy+1][spx+1];
                let top=ltv*(width-(xi%width))/width+rtv*(xi%width)/width;
                let bottom=lbv*(width-(xi%width))/width+rbv*(xi%width)/width;
                return Math.round(top*(width-(yi%width))/width+bottom*(yi%width)/width);
            })
        })
        console.log(seedMap);
        console.log(this.powermap);
    }
    /**
     * 通过坐标找动物
     */
    findAnimalByPoint(x:number,y:number){
            return this.animalPoints[x][y];
    }

    forEach(fn:(e:Animal)=>any){
        this.animalList.forEach(fn);
    }

    /**
     * 获取动物列表，用于保存进度
     * @returns 
     */
    getAnimalList(){
        return zipAnimalList(Array.from(this.animalList.values()));
    }

    /**
     * 获取能量地图，用于保存进度
     * @returns 
     */
    getPowerMap(){
        return this.powermap
    }

    /**
     * 从自然界获得能量
     * @param life 
     */
    getPowerFromNature(life:Animal){
        if(this.powermap[life.x][life.y]>=5){
            life.power+=5;
            this.powermap[life.x][life.y]-=5;
        }
        
    }
    /**
     * 通过id杀死生物
     * @param id 
     */
    killAnimalByid(id:number){
        let animal=this.animalList.get(id);
        if(animal){
            this.animalPoints[animal.x][animal.y]=null;
            status.die_age_total+=animal.age
        }
        status.now_die++;
        // delete animal;
        return this.animalList.delete(id);
    }
    killAnimalByPoint(x:number,y:number){
        let animal=this.findAnimalByPoint(x,y);
        this.animalPoints[x][y]=null;
        status.now_die++;
        if(animal){
            status.die_age_total+=animal.age
        }
        return animal?this.animalList.delete(animal.id):false;
    }
    reducePower(animal:Animal,power:number=1){
        animal.power-=power;
        if(status.conifg.COE){
            this.powermap[animal.x][animal.y]+=power
        }
    }
    run(ctx:CanvasRenderingContext2D){
        let imageData=ctx.getImageData(0,0,500,500);
        
        this.powermap.forEach((v,i)=>{
            v.forEach((vv,ii)=>{
                let pxv=(255-vv)<=0?0:(255-vv);
                let pxId=ii * (imageData.width * 4) + (i * 4);
                imageData.data[pxId]=pxv;
                imageData.data[pxId+1]=pxv;
                imageData.data[pxId+2]=pxv;
                imageData.data[pxId+3]=255;
            })
        })
        // console.log(this.powermap);
        // console.log(imageData);
        if(status.conifg.showPower){
            ctx.putImageData(imageData,0,0);
        }
        
        let plantCount=0;
        let animalCount=0;
        let dink=0;
        let stabilize =0;
        this.animalList.forEach(e=>{
            
            if(this.animalPoints[e.x][e.y]!=e){
                throw new Error(`id为${e.id}的生物自述坐标与上帝登记的坐标不一致`);
            }
            if(!(status.times%10)){
                this.reducePower(e);
            }
            
            if(e.wantbreed==0){
                dink++;
            }
            if(e.wantEat==0&&e.wantsun){
                plantCount++;
            }
            if(e.wantsun==0&&e.wantEat){
                animalCount++;
            }
            if(e.wantChange==0){
                stabilize ++;
            }
            if(e.power<=0){
                let rel=this.killAnimalByid(e.id);
                if(rel){
                    status.die_hunger++;
                }
            }
            e.age++;
            
            e.run(this);

            if(status.conifg.showAnimal){
                ctx.beginPath();
                ctx.strokeStyle = `#${(e.wantEat).toString(16)}${e.wantEat.toString(16)}${(15-e.wantmove).toString(16)}${e.wantsun.toString(16)}${e.wantbreed.toString(16)}${e.wantbreed.toString(16)}`;
                ctx.moveTo(e.x,e.y);
                ctx.lineTo(e.x+1,e.y+1);
                ctx.stroke();
            }
            
        });
        if(status.now_die){
            status.age_want_life=Math.floor(status.die_age_total/status.now_die);
        }
        status.dink=dink;
        status.plants=plantCount;
        status.animals=animalCount;
        status.stabilize =stabilize ;
    }
    toJSON(){
        return this.toObject();
    }
    toObject(){
        return Array.from(this.animalList.values()).map(v=>v.toObject())
    }

    tryEat(me:Animal,x:number,y:number){
        let food= this.findAnimalByPoint(x,y);
        if(food){
            if(me.power>food.power){
                me.power=(me.power+food.power-2);
                status.die_prey++;
                return this.killAnimalByid(food.id);
            }
        }
        return false;
    }

    /**
     * 更新或创建生物地图
     * @param animals 
     */
    updateAnimals(animals:Animal[]=[]){
        this.animalPoints=new Array(500).fill(null);
        this.animalPoints=this.animalPoints.map(e=>{
            return (new Array(500)).fill(null)
        });
        // console.log(animals);
        // console.log(this.animalPoints);
        if(!animals.length){
            animals.push(new Animal({x:250,y:250}))
        }
        animals.forEach(e=>{
            this.animalList.set(e.id,e);
            if(e.id>=this.nextid){
                this.nextid=e.id+1;
            }
            try{
                this.animalPoints[e.x][e.y]=e;
            }catch(er){
                console.error(this.animalPoints[e.x],e.x);
            }
        })
    }
    /**
     * 更新或创建资源地图
     * @param powermap 
     */
    updatePowerMap(powermap:number[][]=[]){
        if(powermap.length){
            this.powermap=powermap;
        }else{
            this.powermap=this.powermap.map(e=>{
                return (new Array(500)).fill(255)
            });
            this.createPowerMap();
        }
    }
    
}